package com.server.monitor;


import com.server.entity.Registry;
import com.server.entity.ServiceInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.Set;

/**
 * 微服务监控组件
 */
@Component
public class ServiceAliveMonitor implements ApplicationRunner {

    public static final Logger log = LoggerFactory.getLogger(ServiceAliveMonitor.class);

    public static final Long CHECK_ALIVE_TIME = 60 * 1000L;


    private Daemon daemon = new Daemon();

    private ClearRecentlyChangedDaemon clearRecentlyChangedDaemo = new ClearRecentlyChangedDaemon();

    private Registry registry = Registry.getInstance();
    /**
     * 启动后台线程
     *
     */

    public void start() {
        daemon.start();
        clearRecentlyChangedDaemo.start();
    }


    /**
     * 服务server初始化启动时执行
     * @param args
     * @throws Exception
     */
    @Override
    public void run(ApplicationArguments args) throws Exception {
        this.daemon.setName("serviceAliveMonitor");
        this.start();
    }

    /**
     * 负责检查服务实例是否存活
     */
    public class Daemon extends Thread{

        private Registry registry = Registry.getInstance();

        @Override
        public void run() {
            //每隔60秒检查一次
            Long checkTime = 0L;
            while (true) {
                checkTime = checkTime + 1 ;
                log.info("第[{}]检查服务实例是否存活",checkTime);
                try {
                    //服务注册表
                    Map<String, Map<String, ServiceInstance>> registryMap = this.registry.getRegistry();
                    Set<String> keys = registryMap.keySet();
                    if (!CollectionUtils.isEmpty(keys)) {
                        for (String serviceName : keys) {
                            Map<String, ServiceInstance> instanceMap = registryMap.get(serviceName);
                            for (ServiceInstance serviceInstance : instanceMap.values()) {
                                //检查最后的心跳的时间与当前时间是否超过60秒
                                Boolean alive = serviceInstance.getLease().isAlive();
                                if (alive) {
                                    this.registry.remove(serviceName,serviceInstance.getServiceInstanceId());
                                }
                            }

                        }

                    }
                    else {
                        log.info("当前server没有CLIENT进行注册");
                }
                    Thread.sleep(CHECK_ALIVE_TIME);
                } catch (InterruptedException e) {
                    log.warn("检查服务实例失败");
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 每3分钟清理一次最近改变的队列
     */
    private class ClearRecentlyChangedDaemon extends Thread{

        @Override
        public void run() {
            while (true) {
                log.info("每3分钟清理一次最近改变的队列");
                try {
                    Thread.sleep(180 * 1000);
                } catch (InterruptedException e) {
                    log.error("清理最近改变的队列发生异常",e);
                }
                synchronized (registry) {
                    registry.getRecentlyChangedQueue().clear();
                }
            }
        }
    }
}
